package cn.yunyichina.provider.pay.service.impl;

import cn.yunyichina.provider.framework.dubbo.service.AlipayService;
import cn.yunyichina.provider.framework.dubbo.service.HymedService;
import cn.yunyichina.provider.framework.dubbo.service.PacityService;
import cn.yunyichina.provider.framework.dubbo.service.WechatPayService;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.iface.entity.dto.hymed.PaymentQueryRequestDTO;
import cn.yunyichina.provider.iface.entity.dto.hymed.PaymentQueryResponseDTO;
import cn.yunyichina.provider.iface.entity.dto.pacity.PacityOrderQueryRequestDTO;
import cn.yunyichina.provider.iface.entity.dto.pacity.PacityOrderQueryResponseDTO;
import cn.yunyichina.provider.iface.entity.dto.pay.*;
import cn.yunyichina.provider.iface.entity.pay.PayCode;
import cn.yunyichina.provider.pay.constant.ResponseEnum;
import cn.yunyichina.provider.pay.dao.PaymentJournalDao;
import cn.yunyichina.provider.pay.entity.PaymentJournal;
import cn.yunyichina.provider.pay.entity.PaymentSetting;
import cn.yunyichina.provider.pay.exception.PaySettingNotFoundException;
import cn.yunyichina.provider.pay.model.vo.PayOrderQueryVO;
import cn.yunyichina.provider.pay.service.BaseOrderService;
import cn.yunyichina.provider.pay.service.OrderService;
import cn.yunyichina.utils.convert.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * 支付订单查询
 * Created by Lullaby on 2017/5/18.
 */
@Service
public class OrderServiceImpl extends BaseOrderService implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private PaymentJournalDao paymentJournalDao;

    /**
     * 查询订单
     *
     * @param json
     * @return
     */
    public Response queryOrder(String json) {
        logger.info("OrderServiceImpl.queryOrder.json -> {}", json);
        Response response = new Response();
        try {
            Map<String, String> params = JsonUtils.parseObject(json, Map.class);
            String payCode = params.get("pay_code");
            switch (PayCode.valueOf(payCode)) {
                case WECHAT:
                    return queryWechatOrder(params);
                case WECHATMEDICAL:
                    return queryWechatMedicalOrder(params);
                case ALIPAY:
                    return queryAlipayOrder(params);
                case PACITY:
                    return queryPacityOrder(params);
                case HYMEDUNION:
                    return queryHymedUnionOrder(params);
                default:
                    return response.buildResultCodeAndMessage(
                            ResponseEnum.UNKNOWN_PAY_CODE.getCode(),
                            ResponseEnum.UNKNOWN_PAY_CODE.getMessage()
                    );
            }
        } catch (PaySettingNotFoundException e) {
            logger.error("OrderServiceImpl.queryOrder.PaySettingNotFoundException", e);
            return response.buildResultCodeAndMessage(
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getCode(),
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getMessage()
            );
        } catch (Exception e) {
            logger.error("OrderServiceImpl.queryOrder.Exception", e);
            return response.buildResultCodeAndMessage(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage()
            );
        }
    }

    /**
     * 查询微信支付订单
     *
     * @param params
     * @return
     */
    private Response queryWechatOrder(Map<String, String> params) throws PaySettingNotFoundException {
        if (!checkOrderQueryParameters(params)) return invalidPayParamsResponse();

        Response response = new Response();

        WechatOrderQueryRequestDTO queryRequest = buildQueryWechatOrderParameters(params);
        logger.info("OrderServiceImpl.queryWechatOrder.queryRequest -> {}", JsonUtils.toJsonString(queryRequest));

        ResCommon<WechatOrderQueryResponseDTO> queryResponse = WechatPayService.getWechatPayClient().queryWechatOrder(queryRequest);
        logger.info("OrderServiceImpl.queryWechatOrder.queryResponse -> {}", JsonUtils.toJsonString(queryResponse));

        if (queryResponse.isSuccess()) {
            response.setResult(JsonUtils.toJsonString(queryResponse.getResult()));
        } else {
            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    JsonUtils.toJsonString(queryResponse.getResult())
            );
        }

        return response;
    }

    /**
     * 查询微信医疗支付订单
     *
     * @param params
     * @return
     */
    private Response queryWechatMedicalOrder(Map<String, String> params) {
        Response response = new Response();
        return response;
    }

    /**
     * 查询支付宝支付订单
     *
     * @param params
     * @return
     */
    private Response queryAlipayOrder(Map<String, String> params) throws PaySettingNotFoundException {
        if (!checkOrderQueryParameters(params)) return invalidPayParamsResponse();

        Response response = new Response();

        AlipayOrderQueryRequestDTO queryRequest = buildQueryAlipayOrderParameters(params);
        logger.info("OrderServiceImpl.queryAlipayOrder.queryRequest -> {}", JsonUtils.toJsonString(queryRequest));

        ResCommon<AlipayOrderQueryResponseDTO> queryResponse = AlipayService.getAlipayClient().queryAlipayOrder(queryRequest);
        logger.info("OrderServiceImpl.queryAlipayOrder.queryResponse -> {}", JsonUtils.toJsonString(queryResponse));

        if (queryResponse.isSuccess()) {
            response.setResult(JsonUtils.toJsonString(queryResponse.getResult()));
        } else {
            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    JsonUtils.toJsonString(queryResponse.getResult())
            );
        }

        return response;
    }

    /**
     * 查询平安付支付订单
     *
     * @param params
     * @return
     */
    private Response queryPacityOrder(Map<String, String> params) throws Exception {
        if (!checkOrderQueryParameters(params)) return invalidPayParamsResponse();

        Response response = new Response();

        PacityOrderQueryRequestDTO queryRequest = buildQueryPacityOrderRequestDTO(params);
        logger.info("OrderServiceImpl.queryPacityOrder.queryRequest -> {}", JsonUtils.toJsonString(queryRequest));

        ResCommon<PacityOrderQueryResponseDTO> queryResponse = PacityService.getPacityClient().queryPacityOrder(queryRequest);
        logger.info("OrderServiceImpl.queryPacityOrder.queryResponse -> {}", JsonUtils.toJsonString(queryResponse));

        if (queryResponse.isSuccess()) {
            response.setResult(JsonUtils.toJsonString(queryResponse.getResult()));
        } else {
            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    JsonUtils.toJsonString(queryResponse.getResult())
            );
        }

        return response;
    }

    /**
     * 查询河源一卡通平台消费订单
     *
     * @param params
     * @return
     */
    private Response queryHymedUnionOrder(Map<String, String> params) throws PaySettingNotFoundException {
        Response response = new Response();

        if (StringUtils.isEmpty(params.get("app_code")) || StringUtils.isEmpty(params.get("org_code")) ||
                (StringUtils.isEmpty(params.get("order_no")) && StringUtils.isEmpty(params.get("pay_order_no")))) {
            return new Response().buildResultCodeAndMessage(
                    ResponseEnum.PAY_INVALID_PARAMETERS.getCode(),
                    ResponseEnum.PAY_INVALID_PARAMETERS.getMessage()
            );
        }

        String appCode = params.get("app_code");
        String orgCode = params.get("org_code");
        String payCode = params.get("pay_code");
        short payMode = (short) getPayModeByPayCode(payCode);
        String orderNo = params.get("order_no");
        String payOrderNo = params.get("pay_order_no");


        PaymentSetting paymentSetting = getPaymentSetting(appCode, orgCode, payMode);

        PaymentQueryRequestDTO queryRequestDTO = new PaymentQueryRequestDTO();
        queryRequestDTO.setAppCode(appCode);
        queryRequestDTO.setOrgCode(orgCode);
        queryRequestDTO.setPayCode(payCode);
        queryRequestDTO.setMer_cd(paymentSetting.getMerchantAccount());
        if (StringUtils.isEmpty(orderNo)) {
            queryRequestDTO.setCt_orderid(payOrderNo);
        } else if (StringUtils.isEmpty(payOrderNo)) {
            queryRequestDTO.setOrderid(orderNo);
        } else if (!StringUtils.isEmpty(orderNo) && !StringUtils.isEmpty(payOrderNo)) {
            queryRequestDTO.setOrderid(orderNo);
            queryRequestDTO.setCt_orderid(payOrderNo);
        }

        ResCommon<PaymentQueryResponseDTO> queryResponse = HymedService.getHyMedClient().queryPayment(queryRequestDTO);
        logger.info("OrderServiceImpl.queryHymedUnionOrder.queryResponse -> {}", JsonUtils.toJsonString(queryResponse));
        if (!queryResponse.isSuccess()) {
            return new Response().buildResultCodeAndMessageAndResult(
                    queryResponse.getResultCode(),
                    queryResponse.getResultMessage(),
                    JsonUtils.toJsonString(queryResponse.getResult())
            );
        }

        response.setResult(JsonUtils.toJsonString(queryResponse.getResult()));

        return response;
    }

    /**
     * 对外接口：查询支付订单
     *
     * @param data
     * @return
     */
    public ResponseObject queryOrderPay(String data) {
        Map<String, String> params = JsonUtils.parseObject(data, Map.class);

        if (CollectionUtils.isEmpty(params) ||
                StringUtils.isEmpty(params.get("pay_code")) ||
                StringUtils.isEmpty(params.get("order_no"))) {
            return new ResponseObject().buildResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(), ResponseEnum.Common.INVALID.getMessage()
            );
        }

        String appId = params.get("app_id");
        if (StringUtils.isEmpty(appId)) {
            PaymentJournal payment = new PaymentJournal();
            payment.setOrderNo(params.get("order_no"));
            List<PaymentJournal> journals = paymentJournalDao.select(payment);
            if (CollectionUtils.isEmpty(journals)) {
                return new ResponseObject().buildResultCodeAndMessage(
                        ResponseEnum.NOT_FOUND_TRANSACTION.getCode(), ResponseEnum.NOT_FOUND_TRANSACTION.getMessage()
                );
            }
            params.put("app_id", journals.get(0).getPayAppId());
        }

        try {
            String payCode = params.get("pay_code");
            switch (PayCode.valueOf(payCode)) {
                case WECHAT:
                    return queryWechatPayOrder(params);
                case ALIPAY:
                    return queryAlipayPayOrder(params);
                case PACITY:
                    return queryPacityPayOrder(params);
                default:
                    return new ResponseObject().buildResultCodeAndMessage(
                            ResponseEnum.UNKNOWN_PAY_CODE.getCode(),
                            ResponseEnum.UNKNOWN_PAY_CODE.getMessage()
                    );
            }
        } catch (PaySettingNotFoundException e) {
            logger.error("OrderServiceImpl.queryOrderPay.PaySettingNotFoundException", e);
            return new ResponseObject().buildResultCodeAndMessage(
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getCode(),
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getMessage()
            );
        } catch (Exception e) {
            logger.error("OrderServiceImpl.queryOrderPay.Exception", e);
            return new ResponseObject().buildResultCodeAndMessage(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage()
            );
        }
    }

    /**
     * 对外接口：查询微信支付订单
     *
     * @param params
     * @return
     */
    private ResponseObject queryWechatPayOrder(Map<String, String> params) {
        return null;
    }

    /**
     * 对外接口：查询支付宝支付订单
     *
     * @param params
     * @return
     * @throws PaySettingNotFoundException
     */
    private ResponseObject queryAlipayPayOrder(Map<String, String> params) throws PaySettingNotFoundException {
        ResponseObject response = new ResponseObject();

        AlipayOrderQueryRequestDTO queryRequest = buildQueryAlipayOrderParameters(params);
        logger.info("OrderServiceImpl.queryAlipayPayOrder.queryRequest -> {}", JsonUtils.toJsonString(queryRequest));

        ResCommon<AlipayOrderQueryResponseDTO> queryResponse = AlipayService.getAlipayClient().queryAlipayOrder(queryRequest);
        logger.info("OrderServiceImpl.queryAlipayPayOrder.queryResponse -> {}", JsonUtils.toJsonString(queryResponse));

        if (queryResponse.isSuccess()) {
            AlipayOrderQueryResponseDTO alipayResponse = queryResponse.getResult();
            PayOrderQueryVO orderQueryVO = new PayOrderQueryVO();
            orderQueryVO.setOrderNo(alipayResponse.getAlipayTradeQueryResponse().getOutTradeNo());
            orderQueryVO.setTradeNo(alipayResponse.getAlipayTradeQueryResponse().getTradeNo());
            orderQueryVO.setTradeStatus(alipayResponse.getAlipayTradeQueryResponse().getTradeStatus().toString());
            orderQueryVO.setTotalAmount(alipayResponse.getAlipayTradeQueryResponse().getTotalAmount());
            orderQueryVO.setPayAmount(alipayResponse.getAlipayTradeQueryResponse().getBuyerPayAmount());
            orderQueryVO.setDeductAmount(alipayResponse.getAlipayTradeQueryResponse().getPointAmount());
            orderQueryVO.setOpenId(alipayResponse.getAlipayTradeQueryResponse().getBuyerUserId());
            orderQueryVO.setTradeTime(alipayResponse.getAlipayTradeQueryResponse().getSendPayDate());

            response.setResultObject(orderQueryVO);
        } else {
            AlipayOrderQueryResponseDTO responseDTO = queryResponse.getResult();

            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    responseDTO.getAlipayTradeQueryResponse()
            );
        }

        return response;
    }

    /**
     * 对外接口：查询平安付支付订单
     *
     * @param params
     * @return
     */
    private ResponseObject queryPacityPayOrder(Map<String, String> params) {
        return null;
    }

    /**
     * 撤销订单
     *
     * @param json
     * @return
     */
    public Response reverseOrder(String json) {
        logger.info("OrderServiceImpl.reverseOrder.json -> {}", json);
        Response response = new Response();
        try {
            Map<String, String> params = JsonUtils.parseObject(json, Map.class);
            String payCode = params.get("pay_code");
            switch (PayCode.valueOf(payCode)) {
                case WECHAT:
                    return reverseWechatOrder(params);
                case ALIPAY:
                    return cancelAlipayOrder(params);
                default:
                    return response.buildResultCodeAndMessage(
                            ResponseEnum.UNKNOWN_PAY_CODE.getCode(),
                            ResponseEnum.UNKNOWN_PAY_CODE.getMessage()
                    );
            }
        } catch (PaySettingNotFoundException e) {
            logger.error("OrderServiceImpl.reverseOrder.PaySettingNotFoundException", e);
            return response.buildResultCodeAndMessage(
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getCode(),
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getMessage()
            );
        } catch (Exception e) {
            logger.error("OrderServiceImpl.reverseOrder.Exception", e);
            return response.buildResultCodeAndMessage(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage()
            );
        }
    }

    /**
     * 撤销微信支付订单
     *
     * @param params
     * @return
     */
    private Response reverseWechatOrder(Map<String, String> params) throws PaySettingNotFoundException {
        if (!checkOrderReverseParameters(params)) return invalidPayParamsResponse();

        Response response = new Response();

        WechatOrderReverseRequestDTO reverseRequest = buildReverseWechatOrderParameters(params);
        logger.info("OrderServiceImpl.reverseWechatOrder.reverseRequest -> {}", JsonUtils.toJsonString(reverseRequest));

        ResCommon<WechatOrderReverseResponseDTO> reverseResponse = WechatPayService.getWechatPayClient().reverseWechatOrder(reverseRequest);
        logger.info("OrderServiceImpl.reverseWechatOrder.reverseResponse -> {}", JsonUtils.toJsonString(reverseResponse));

        if (reverseResponse.isSuccess()) {
            response.setResult(JsonUtils.toJsonString(reverseResponse.getResult()));
        } else {
            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    JsonUtils.toJsonString(reverseResponse.getResult())
            );
        }

        return response;
    }

    /**
     * 撤销支付宝支付订单
     *
     * @param params
     * @return
     */
    private Response cancelAlipayOrder(Map<String, String> params) throws PaySettingNotFoundException {
        if (!checkOrderReverseParameters(params)) return invalidPayParamsResponse();

        Response response = new Response();

        AlipayOrderCancelRequestDTO cancelRequest = buildCancelAlipayOrderParameters(params);
        logger.info("OrderServiceImpl.cancelAlipayOrder.cancelRequest -> {}", JsonUtils.toJsonString(cancelRequest));

        ResCommon<AlipayOrderCancelResponseDTO> cancelResponse = AlipayService.getAlipayClient().cancelAlipayOrder(cancelRequest);
        logger.info("OrderServiceImpl.cancelAlipayOrder.cancelResponse -> {}", JsonUtils.toJsonString(cancelResponse));

        if (cancelResponse.isSuccess()) {
            response.setResult(JsonUtils.toJsonString(cancelResponse.getResult()));
        } else {
            response.setResultCodeAndMessageAndResult(
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getCode(),
                    ResponseEnum.ORDER_QUERY_EXCEPTION.getMessage(),
                    JsonUtils.toJsonString(cancelResponse.getResult())
            );
        }

        return response;
    }

}
